/*
 * @(#)AggregateMemFunc.java        1.0 2000/05/09
 *
 * This file is part of Xfuzzy 3.0, a design environment for fuzzy logic
 * based systems.
 *
 * (c) 2000 IMSE-CNM. The authors may be contacted by the email address:
 *                    xfuzzy-team@imse.cnm.es
 *
 * Xfuzzy is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * Xfuzzy is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */


package xfuzzy.lang;

/**
 * Funcion de pertenencia formada por la agregacion de un conjunto
 * de conclusiones
 * 
 * @author Francisco Jose Moreno Velo
 *
 */
public class AggregateMemFunc implements MemFunc {

	//----------------------------------------------------------------------------//
	//                            MIEMBROS P�BLICOS                               //
	//----------------------------------------------------------------------------//

	/**
	 * Lista de conclusiones a agregar
	 */
	public ImpliedMemFunc conc[];
	
	/**
	 * Valor de las entradas, para las funciones de tipo param�trico
	 * (Takagi-Sugeno)
	 */
	public double input[];

	//----------------------------------------------------------------------------//
	//                            MIEMBROS PRIVADOS                              //
	//----------------------------------------------------------------------------//

	/**
	 * Universo de discurso de la funci�n de pertenencia
	 */
	private Universe u;

	/**
	 * Base de reglas de la que procede la funci�n de pertenencia agregada
	 */
	private KnowledgeBase mod;

	//----------------------------------------------------------------------------//
	//                                CONSTRUCTOR                                 //
	//----------------------------------------------------------------------------//

	/**
	 * Constructor
	 * @param universe Universo de discurso de la funci�n de pertenencia
	 * @param mod Base de reglas de la que procede la funci�n de pertenencia 
	 */
	public AggregateMemFunc(Universe universe, KnowledgeBase mod) {
		this.u = universe;
		this.mod = mod;
		this.conc = new ImpliedMemFunc[0];
	}

 	//----------------------------------------------------------------------------//
	//                             M�TODOS P�BLICOS                               //
	//----------------------------------------------------------------------------//

	/**
	 * A�ade una nueva funci�n a la agregaci�n
	 */
	public void add(ImpliedMemFunc imf) {
		ImpliedMemFunc amf[] = new ImpliedMemFunc[this.conc.length+1];
		System.arraycopy(this.conc,0,amf,0,this.conc.length);
		amf[this.conc.length] = imf;
		this.conc = amf;
	}

	/**
	 * Calcula el grado de pertenencia de la agregaci�n 
	 */
	public double compute(double x) {
		double degree = this.conc[0].compute(x);
		for(int i=1; i<this.conc.length; i++)
			degree = this.mod.operation.also.compute(degree, this.conc[i].compute(x));
		return degree;
	}

	/**
	 * Aplica el m�todo de concreci�n a la agregaci�n
	 */
	public double defuzzify() {
		return this.mod.operation.defuz.compute(this);
	}

	/**
	 * Obtiene el m�nimo del universo de discurso de la funci�n 
	 */
	public double min() {
		return this.u.min();
	}

	/**
	 * Obtiene el m�ximo del universo de discurso de la funci�n 
	 */
	public double max() {
		return this.u.max();
	}

	/**
	 * Obtiene la divisi�n del universo de discurso de la funci�n 
	 */
	public double step() {
		return this.u.step();
	}

	/**
	 * Analiza si se trata de una agregacion de singularidades 
	 */
	public boolean isDiscrete() {
		for(int i=0; i<conc.length; i++)
			if( !(conc[i].getMF() instanceof xfuzzy.pkg.xfl.mfunc.singleton) ) return false;
		return true;
	} 

	/**
	 * Obtiene los valores de una agregaci�n de singularidades 
	 */
	public double[][] getDiscreteValues() {
		double[][] value = new double[conc.length][2];
		for(int i=0; i<conc.length; i++) {
			value[i][0] = conc[i].getParam()[0];
			value[i][1] = conc[i].getDegree();
		}
		return value;
	}

	/**
	 * Obtiene el grado de activaci�n de una singularidad 
	 */
	public double getActivationDegree(double label) {
		double degree = 0;
		for(int i=0; i<conc.length; i++)
			if(conc[i].center() == label)
				if(degree<conc[i].getDegree()) degree = conc[i].getDegree();
		return degree;
	}
}
